﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using ProtoBuf;

namespace SchemaMonitor.json
{
    [DataContract]
    public class CMetadata : CDictBase
    {
        //Members
        [DataMember(Order = 1)] public string Type;
        [DataMember(Order = 2)] public List<CMetaField> Fields;
        [DataMember(Order = 3)] public List<CConnection>  Connections;




        //Constructor
        public CMetadata(object obj, CUser u, string id) : this(new CDict((Dictionary<string, object>)obj), u, id) { }
        public CMetadata(Dictionary<string, object> dict, CUser u, string id) : this(new CDict(dict),u, id) { }
        public CMetadata(CDict d, CUser u, string id) : base(d)
        {
            Type = d.AsStr("type");
            Fields = d.AsMetaFields("fields");
            Connections = d.AsConnections("connections");

			foreach (var i in this.Connections)
				i.Url = i.Url.Replace(u.UserToken, "[UserToken]").Replace(id, "[Id]");
        }
        private CMetadata() { }
        static CMetadata() { Serializer.PrepareSerializer<CMetadata>(); }

        //Derived
        public bool HasType { get { return !string.IsNullOrEmpty(Type); } }
        public bool HasFields  { get { return null != Fields; } }

        public string Pattern
        {
            get
            {
                var sb = new StringBuilder();
                foreach (var i in Fields)
                {
                    if (sb.Length > 0)
                        sb.Append(",");
                    sb.Append(i.Name);
                }
                return string.Concat(Type, ": ", sb.ToString());
            }
        }

        #region Index
        public bool Has(string name)
        {
            return IndexByName.ContainsKey(name);
        }
        public CMetaField this[string name]
        {
            get
            {
                CMetaField f = null;
                IndexByName.TryGetValue(name, out f);
                return f;
            }
        }
        [NonSerialized]
        private Dictionary<string, CMetaField> _indexByName;
        private Dictionary<string, CMetaField> IndexByName
        {
            get
            {
                if (null == _indexByName || _indexByName.Count != Fields.Count)
                {
                    var d = new Dictionary<string, CMetaField>(Fields.Count);
                    foreach (var i in this.Fields)
                        d.Add(i.Name, i);
                    _indexByName = d;
                }
                return _indexByName;
            }
        }
        #endregion
    }
}
